Micron Document
πŸŽ–οΈGitΠ―Ρ€Π°πŸŽ–οΈ


Displaying Rendered β€’ View raw β€’ Download

specs/005-tak-v2-protocol/plan.md bd2863243bab6eb213401d949839a2bc74dde7e2 (bd286324) Text, 10.30 KB

Implementation Plan: TAK v2 Protocol Integration

Branch: T383838tak_v2 | Date: 2026-05-13 | Spec: T383838specs/005-tak-v2-protocol/spec.md
Input: Feature specification from T383838/specs/005-tak-v2-protocol/spec.md
Status: Retroactive β€” documents existing implementation (PR #5434, 99 files, +4698 lines)

Summary

Upgrades Meshtastic Android's TAK integration from legacy v1 (port 72, PLI + GeoChat only) to TAK v2 (port 78, ATAKPLUGINV2) with zstd dictionary compression and full CoT type coverage. The implementation uses a bidirectional bridge pattern (T383838TAKMeshIntegration) that version-gates output based on firmware capability (T383838Capabilities.supportsTakV2 β‰₯ 2.8.0) while always accepting inbound traffic on both ports. Compression is provided by the T383838meshtastic/TAKPacket-SDK (JitPack) with platform abstraction via expect/actual for iOS stubs.

Technical Context

Language/Version: Kotlin 2.3+ targeting JDK 21 (KMP multi-target)
Primary Dependencies: TAKPacket-SDK v0.1.3 (zstd compression), xmlutil (CoT XML parsing), Ktor Network (TCP), zstd-jni 1.5.7-7, Okio (I/O), Koin 4.2+ (DI), Kermit (logging)
Storage: App-private filesystem for route KML data packages; bundled .p12/.pem certificates for TLS
Testing: T383838commonTest (9 test classes, 65+ test methods), 40 XML fixture files in T383838jvmAndroidMain/resources/tak_test_fixtures/
Target Platform: Android (primary), JVM Desktop (secondary), iOS (stubs only)
Project Type: Mobile app β€” KMP module (T383838core:takserver) + UI integration (T383838feature:settings)
Performance Goals: CoT processing < 100ms; compressed PLI < 100 bytes; fits within ~225-byte usable LoRa payload
Constraints: 237-byte raw LoRa MTU (~225 usable after protobuf framing); PARTIALWAKELOCK for CPU keepalive; mTLS on port 8089
Scale/Scope: 28 CoT type mappings, 2 protocol versions, 3 platform targets, 1 new KMP module + UI screen

Constitution Check

GATE: βœ… All six principles evaluated and satisfied.

β€’ I. Kotlin Multiplatform Core: βœ… All business logic (TAKMeshIntegration, conversions, type mapper, CoT parser, detail stripper, server manager, models, DI module) resides in T383838commonMain. Platform-specific code isolated to:
β€’ T383838jvmAndroidMain: TAKServerJvm (JSSE TLS), TakV2Compressor (zstd-jni via SDK), TakCertLoader, TAKClientConnection
β€’ T383838androidMain: AtakFileWriter (SAF/private dirs), TakPermissionUtil (runtime permissions)
β€’ T383838jvmMain: AtakFileWriter (desktop filesystem), TakPermissionUtil (no-op)
β€’ T383838iosMain: TAKServerIos (no-op), TakV2Compressor (uncompressed stub), AtakFileWriter (stub)
β€’ II. Zero Lint Tolerance: βœ… Verification commands:
T282828
./gradlew spotlessApply spotlessCheck detekt :core:takserver:allTests :feature:settings:allTests

β€’ III. Compose Multiplatform UI: βœ… T383838TAKConfigItemList.kt uses Compose Multiplatform components (T383838DropDownPreference, T383838SwitchPreference, T383838TitledCard). No direct Android Jetpack Compose imports. Float values use T383838NumberFormatter.format() where displayed.

β€’ IV. Privacy First: βœ… No PII/location/crypto keys logged. CoT data stays local to device/mesh. T383838core/proto submodule not modified (read-only upstream). Certificates bundled as resources, not logged.

β€’ V. Design Standards Compliance: βœ… TAK config UI uses M3 components (SwitchPreference, DropDownPreference). Cross-Platform Spec: TAKPacket-SDK defines shared wire protocol behavior; Android-specific UI is N/A for cross-platform spec (ATAK integration is Android/JVM-only; iOS uses stubs).

β€’ VI. Verify Before Push: βœ… Local verification:
T282828
./gradlew spotlessApply spotlessCheck detekt assembleDebug :core:takserver:allTests :feature:settings:allTests
gh pr checks T79c0ff5434


Project Structure

Documentation (this feature)

T282828
specs/005-tak-v2-protocol/
β”œβ”€β”€ plan.md # This file
β”œβ”€β”€ research.md # Phase 0: Technology decisions and rationale
β”œβ”€β”€ data-model.md # Phase 1: Entity models and state machines
β”œβ”€β”€ quickstart.md # Phase 1: Developer onboarding guide
β”œβ”€β”€ contracts/ # Phase 1: Wire protocol contracts
β”‚ └── wire-protocol.md
└── tasks.md # Phase 2 output (/speckit.tasks command)

Source Code (repository root)

T282828
core/takserver/
β”œβ”€β”€ build.gradle.kts # Module config + TAKPacket-SDK dependency
└── src/
β”œβ”€β”€ commonMain/kotlin/org/meshtastic/core/takserver/
β”‚ β”œβ”€β”€ di/CoreTakServerModule.kt # Koin DI wiring
β”‚ β”œβ”€β”€ TAKMeshIntegration.kt # Bidirectional bridge (main orchestrator)
β”‚ β”œβ”€β”€ TAKServer.kt # Platform interface (expect)
β”‚ β”œβ”€β”€ TAKServerManager.kt # Lifecycle + offline queue
β”‚ β”œβ”€β”€ TAKPacketV2Conversion.kt # CoT ↔ TAKPacketV2 (v2 protocol)
β”‚ β”œβ”€β”€ TAKPacketConversion.kt # CoT ↔ TAKPacket (v1 legacy)
β”‚ β”œβ”€β”€ TakV2Compressor.kt # Zstd compression (expect)
β”‚ β”œβ”€β”€ TakV2TypeMapper.kt # CoT type string ↔ enum (28 mappings)
β”‚ β”œβ”€β”€ CoTDetailStripper.kt # Strip 16 bloat elements for MTU
β”‚ β”œβ”€β”€ CoTXmlParser.kt # Streaming XML β†’ CoTMessage
β”‚ β”œβ”€β”€ CoTXmlDataClasses.kt # Serializable CoT data model
β”‚ β”œβ”€β”€ CoTXmlFrameBuffer.kt # TCP stream framing
β”‚ β”œβ”€β”€ CoTXml.kt # CoTMessage β†’ XML serialization
β”‚ β”œβ”€β”€ CoTConversion.kt # Shared conversion helpers
β”‚ β”œβ”€β”€ TakConversionHelpers.kt # Coordinate scaling utilities
β”‚ β”œβ”€β”€ RouteDataPackageGenerator.kt # Route β†’ KML data package
β”‚ β”œβ”€β”€ TAKDataPackageGenerator.kt # Connection .zip export
β”‚ β”œβ”€β”€ TAKModels.kt # Domain models
β”‚ β”œβ”€β”€ TAKDefaults.kt # Constants and defaults
β”‚ β”œβ”€β”€ TAKPrefXmlDataClasses.kt # ATAK preference XML schema
β”‚ β”œβ”€β”€ TakFixtureLoader.kt # Test fixture loading (expect)
β”‚ β”œβ”€β”€ TakMeshTestRunner.kt # In-app diagnostic runner
β”‚ β”œβ”€β”€ AtakFileWriter.kt # Filesystem abstraction (expect)
β”‚ β”œβ”€β”€ XmlUtils.kt # XML escaping (5 special chars)
β”‚ └── ZipArchiver.kt # ZIP creation (expect)
β”œβ”€β”€ commonTest/kotlin/.../
β”‚ β”œβ”€β”€ CoTConversionTest.kt
β”‚ β”œβ”€β”€ CoTDetailStripperTest.kt
β”‚ β”œβ”€β”€ CoTXmlFrameBufferTest.kt
β”‚ β”œβ”€β”€ CoTXmlParserTest.kt
β”‚ β”œβ”€β”€ CoTXmlTest.kt
β”‚ β”œβ”€β”€ TAKDefaultsTest.kt
β”‚ β”œβ”€β”€ TAKPacketConversionTest.kt
β”‚ β”œβ”€β”€ TAKPacketV2RawDetailTest.kt
β”‚ └── XmlUtilsTest.kt
β”œβ”€β”€ jvmAndroidMain/kotlin/.../
β”‚ β”œβ”€β”€ TAKServerJvm.kt # JSSE mTLS implementation
β”‚ β”œβ”€β”€ TAKClientConnection.kt # Per-client state machine
β”‚ β”œβ”€β”€ TakCertLoader.kt # Certificate loading
β”‚ β”œβ”€β”€ TakV2Compressor.kt # Zstd actual (via TAKPacket-SDK)
β”‚ β”œβ”€β”€ TakFixtureLoader.kt # JVM resource loading
β”‚ └── ZipArchiver.kt # java.util.zip actual
β”œβ”€β”€ jvmAndroidMain/resources/
β”‚ β”œβ”€β”€ tak_certs/ # Bundled mTLS certificates
β”‚ └── tak_test_fixtures/ # 40 CoT XML fixtures
β”œβ”€β”€ androidMain/kotlin/.../
β”‚ └── AtakFileWriter.kt # SAF/private directory writer
β”œβ”€β”€ jvmMain/kotlin/.../
β”‚ └── AtakFileWriter.kt # Desktop filesystem writer
└── iosMain/kotlin/.../
β”œβ”€β”€ TAKServerIos.kt # No-op server
β”œβ”€β”€ TakV2Compressor.kt # Uncompressed stub (flags=0xFF)
β”œβ”€β”€ AtakFileWriter.kt # No-op
β”œβ”€β”€ TakFixtureLoader.kt # No-op
└── ZipArchiver.kt # No-op

feature/settings/src/
β”œβ”€β”€ commonMain/kotlin/.../radio/component/
β”‚ └── TAKConfigItemList.kt # Compose UI (team, role, server toggle)
β”œβ”€β”€ commonMain/kotlin/.../tak/
β”‚ └── TakPermissionUtil.kt # Permission interface (expect)
β”œβ”€β”€ androidMain/kotlin/.../tak/
β”‚ └── TakPermissionUtil.kt # ACCESS_LOCAL_NETWORK (API 37+)
β”œβ”€β”€ jvmMain/kotlin/.../tak/
β”‚ └── TakPermissionUtil.kt # No-op
└── iosMain/kotlin/.../tak/
└── TakPermissionUtil.kt # No-op

core/model/src/commonMain/kotlin/.../
└── Capabilities.kt # supportsTakV2 (>= 2.8.0)

core/service/src/androidMain/kotlin/.../
└── MeshService.kt # PARTIAL_WAKE_LOCK for TAK server

Structure Decision: KMP multi-module architecture. New T383838core:takserver module contains all TAK business logic in T383838commonMain with platform actuals for TLS, compression, and filesystem. UI lives in the existing T383838feature:settings module. Wake lock integration in existing T383838core:service.

Complexity Tracking

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Violation β”‚ Wh… β”‚ Simpler Alternative Rejected Because β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ T383838jvmAndroidMain shared source set β”‚ TA… β”‚ Separate T383838androidMain/T383838jvmMain actuals would duplicat… β”‚
β”‚ Regex-based XML stripping (not DOM) β”‚ T383838Co… β”‚ Full DOM parsing adds allocation overhead and requi… β”‚
β”‚ Branch name T383838tak_v2 (no prefix) β”‚ Pr… β”‚ N/A β€” not a new branch β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Served by rngit 1.5.0 - Generated in 0.05s